package com.budwk.app.sqfw.services.datamange.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.budwk.app.common.config.AppException;
import com.budwk.app.sqfw.dto.onlineExcel.SqfwExcelOnlineAllDTO;
import com.budwk.app.sqfw.dto.onlineExcel.SqfwFormSummaryOnlineDTO;
import com.budwk.app.sqfw.models.*;
import com.budwk.app.sqfw.services.SqfwFormsummaryNewService;
import com.budwk.app.sqfw.services.datamange.DataMangeCommunityService;
import com.budwk.app.sqfw.services.datamange.DataMangeDistrictService;
import com.budwk.app.sqfw.services.datamange.DataMangeStreetCheckService;
import com.budwk.app.sqfw.utils.CommunityDataCleanUtils;
import com.budwk.app.sqfw.vo.SqfwDataMangeCheckVO;
import com.budwk.app.sqfw.vo.SqfwDataMangeVO;
import com.budwk.app.sys.models.Sys_user;
import com.budwk.app.sys.services.SysUserService;
import com.budwk.app.util.ThreadPoolExecutorUtil;
import com.budwk.starter.common.page.Pagination;
import com.budwk.starter.common.result.ResultCode;
import com.budwk.starter.database.service.BaseServiceImpl;
import com.budwk.starter.security.utils.SecurityUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.nutz.aop.interceptor.ioc.TransAop;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.sql.Criteria;
import org.nutz.dao.util.cri.SqlExpressionGroup;
import org.nutz.ioc.aop.Aop;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.random.R;
import org.nutz.plugins.wkcache.annotation.CacheRemove;

import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
@IocBean(args = {"refer:dao"})
public class DataMangeStreetCheckServiceImpl extends BaseServiceImpl<Sqfw_datamange_street_check> implements DataMangeStreetCheckService {
    public DataMangeStreetCheckServiceImpl(Dao dao) {
        super(dao);
    }

    @Inject
    private SysUserService sysUserService;

    @Inject
    private SqfwFormsummaryNewService sqfwFormsummaryNewService;

    @Inject
    private DataMangeCommunityService dataMangeCommunityService;

    @Inject
    private DataMangeDistrictService dataMangeDistrictService;

    @Override
    public Pagination page(SqfwDataMangeCheckVO bean) {
        if (null == bean) {
            bean = new SqfwDataMangeCheckVO();
        }
        long startTime = System.currentTimeMillis();
        // 构造查询条件
        Criteria criteria = buildQueryCond(bean);
        log.info("DataMangeStreetCheckServiceImpl-list-SQL: {}", criteria.toString());
        Pagination pagination = dataMangeCommunityService.listPage(bean.getPageNo(), bean.getPageSize(), criteria);
        log.info("DataMangeStreetCheckServiceImpl-list-耗时: {}ms", System.currentTimeMillis() - startTime);
        return pagination;
    }

    @Override
    @Aop(TransAop.READ_COMMITTED)
    public SqfwDataMangeCheckVO check(SqfwDataMangeCheckVO bean) {
        if (null == bean || ObjectUtils.isEmpty(bean.getIds()) || StringUtils.isEmpty(bean.getType())) {
            throw new AppException(ResultCode.PARAM_ERROR.getMsg());
        }
        return communityDataCheckByType(bean.getIds(), bean.getType());
    }

    @Override
    public void report(SqfwDataMangeCheckVO bean) {
        if (null == bean) {
            throw new AppException(ResultCode.PARAM_ERROR.getMsg());
        }
        if (StringUtils.isEmpty(bean.getSqfwSummaryId())) {
            throw new AppException("上报流水信息不能为空");
        }
        Sqfw_datamange_street_check sqfwDatamangeStreetCheck = new Sqfw_datamange_street_check();
        BeanUtil.copyProperties(bean, sqfwDatamangeStreetCheck);
        Sys_user sysUser = sysUserService.fetch(SecurityUtil.getUserId());
        sqfwDatamangeStreetCheck
                .setSqfwSummaryId(bean.getSqfwSummaryId())
                .setProvince(sysUser.getProvince())
                .setCity(sysUser.getCity())
                .setDistrict(sysUser.getDistrict())
                .setCounty(sysUser.getCounty())
                .setCommunity(sysUser.getCommunity())
                .setCreateBy(sysUser.getId())
                .setCreateUserName(sysUser.getUsername())
                .setDelFlag(false)
                .setUnitId(sysUser.getUnitId())
                .setUnitName(sysUser.getUnitName())
                .setType(bean.getType())
                .setSubType(StringUtils.isNotEmpty(bean.getSubType()) ? bean.getSubType() : "all")
                .setExcelData(CommunityDataCleanUtils.filtJsonArraySubData(bean.getExcelData(), "_time"))
                .setCreateDate(new Date());
        if (StringUtils.isNotEmpty(sqfwDatamangeStreetCheck.getExcelData())) {
            JSONArray jsonArray = JSONUtil.parseArray(sqfwDatamangeStreetCheck.getExcelData());
            sqfwDatamangeStreetCheck.setRowNum(String.valueOf(jsonArray.size() - 1));
        }
        insert(sqfwDatamangeStreetCheck);

        // 如果上一级主表没有对应数据，则插入， 如果有则更新上报的字段
        ExecutorService executorService = Executors.newSingleThreadExecutor();
        try {
            CompletableFuture.runAsync(() -> {
                updateOrInsertMainTable(bean, sqfwDatamangeStreetCheck, sysUser);
            }, executorService);
        } catch (Exception ex) {
            log.error(ex.getMessage());
        } finally {
            executorService.shutdown();
        }
    }

    /**
     * 如果上一级主表没有对应数据，则插入， 如果有则更新上报的字段
     */
    private void updateOrInsertMainTable(SqfwDataMangeCheckVO bean, Sqfw_datamange_street_check sqfwDatamangeStreetCheck, Sys_user sysUser) {
        // 1.更新表头，从第一级基础大通表shequ.sqfw_datamange_community中取
        Sqfw_datamange_community sqfwDatamangeCommunityHeader = dataMangeCommunityService.fetch(Cnd.where(Sqfw_datamange_community::getExcelSeg, "=", "header"));
        Sqfw_datamange_district sqfwDatamangeDistrictHeader = dataMangeDistrictService.fetch(Cnd.where(Sqfw_datamange_community::getExcelSeg, "=", "header"));
        if (null == sqfwDatamangeDistrictHeader) {
            Sqfw_datamange_district sqfwDatamangeDistrict = new Sqfw_datamange_district();
            BeanUtil.copyProperties(sqfwDatamangeCommunityHeader, sqfwDatamangeDistrict);
            dataMangeDistrictService.insert(sqfwDatamangeDistrict);
        } else {
            dataMangeDistrictService.update(Chain.make("excel_data", sqfwDatamangeCommunityHeader.getExcelData()), Cnd.where("excel_seg", "=", "header"));
        }
        // 2.检查是否有该summaryId对应的记录，有记录则进行更新操作
        Sqfw_datamange_district sqfwDatamangeDistrict = new Sqfw_datamange_district();
        BeanUtil.copyProperties(sqfwDatamangeStreetCheck, sqfwDatamangeDistrict);
        String excelData = sqfwDatamangeDistrict.getExcelData().replaceAll("#595FE0", "#FFFFFF").replaceAll("#FFFAFA", "#000001");

        // 查询详情,如果有记录则更新，否则插入新纪录
        sqfwDatamangeDistrict
                .setSqfwSummaryId(bean.getSqfwSummaryId())
                .setProvince(sysUser.getProvince())
                .setCity(sysUser.getCity())
                .setDistrict(sysUser.getDistrict())
                .setCounty(sysUser.getCounty())
                .setCommunity(sysUser.getCommunity())
                .setCreateBy(sysUser.getId())
                .setCreateUserName(sysUser.getUsername())
                .setDelFlag(false)
                .setUnitId(sysUser.getUnitId())
                .setUnitName(sysUser.getUnitName())
                .setType(bean.getType())
                .setCreateDate(new Date());
        sqfwDatamangeDistrict.setExcelData(excelData);
        batchParseExcelJsonInsert(sqfwDatamangeDistrict);
    }

    /**
     * 批量插入excel解析后的数据到主表
     *
     * @param sqfwDatamangeDistrict
     */
    private void batchParseExcelJsonInsert(Sqfw_datamange_district sqfwDatamangeDistrict) {
        if (null == sqfwDatamangeDistrict) {
            throw new AppException(ResultCode.NULL_DATA_ERROR.getMsg());
        }
        String excelDataList = sqfwDatamangeDistrict.getExcelData();
        List<String> sqfwSummaryIds = Arrays.asList(sqfwDatamangeDistrict.getSqfwSummaryId().split(","));
        try {
            JSONArray jsonArray = JSONUtil.parseArray(excelDataList);
            for (int i = 1; i < jsonArray.size(); i++) {
                String summaryId = sqfwSummaryIds.get(i - 1);
                if (StringUtils.isEmpty(summaryId)) {
                    continue;
                }
                Sqfw_datamange_district sqfwDatamangeDistrictNew = new Sqfw_datamange_district();
                BeanUtil.copyProperties(sqfwDatamangeDistrict, sqfwDatamangeDistrictNew);
                sqfwDatamangeDistrictNew.setSqfwSummaryId(summaryId);
                Map<String, String> updateResultMap = new HashMap<String, String>();// 待更新单元格
                StringBuffer addResultStr = new StringBuffer();// 待追加单元格
                // 查询id对应记录是否存在，存在则更新, 不存在则插入
                Sqfw_datamange_district sqfwDatamangeDistrictSummary
                        = dataMangeDistrictService.fetch(Cnd.where(Sqfw_datamange_district::getSqfwSummaryId, "=", summaryId)
                        .and(Sqfw_datamange_district::getExcelSeg, "!=", "header"));
                if (null == sqfwDatamangeDistrictSummary) {
                    sqfwDatamangeDistrictNew.setId(R.UU32());
                    String excelDataNew = CommunityDataCleanUtils.parseExcelJsonForMainTableNew(summaryId, "", jsonArray.get(i).toString(), updateResultMap, addResultStr);
                    sqfwDatamangeDistrictNew.setExcelData(JSONUtil.toJsonStr(excelDataNew));
                    sqfwDatamangeDistrictNew.setExcelSeg("body");
                    log.info("report insert sql--{}", JSONUtil.toJsonStr(sqfwDatamangeDistrictNew));
                    sqfwDatamangeDistrictNew.setParamData(CommunityDataCleanUtils.parseExcelDataForParamdata(sqfwDatamangeDistrictNew.getExcelData()));
                    dataMangeDistrictService.insert(sqfwDatamangeDistrictNew);
                    continue;
                } else {
                    // 1. 先更新已有字段
                    String excelDataOld = sqfwDatamangeDistrictSummary.getExcelData();
                    String excelDataNew = CommunityDataCleanUtils.parseExcelJsonForMainTableNew(summaryId, excelDataOld, jsonArray.get(i).toString(), updateResultMap, addResultStr);
                    if (ObjectUtils.isNotEmpty(updateResultMap) && StringUtils.isNotEmpty(excelDataOld)) {
                        String excelDataUpdateNew = CommunityDataCleanUtils.parseExcelJsonEachUpdate(summaryId, excelDataOld, updateResultMap);
                        StringBuffer updateSql = new StringBuffer();
                        updateSql.append("UPDATE ").append(CommunityDataCleanUtils.DISTRICT_MAIN_TABLE)
                                .append(" SET excel_data = '").append(JSONUtil.toJsonStr(excelDataUpdateNew))
                                .append("', param_data = '").append(CommunityDataCleanUtils.parseExcelDataForParamdata(excelDataUpdateNew))
                                .append("' WHERE sqfw_summary_id = '").append(summaryId).append("'");
                        log.info("report update sql--{}", updateSql.toString());
                        CommunityDataCleanUtils.updateExcelData(updateSql.toString());
                    }
                    // 2. 后追加不存在的字段
                    if (ObjectUtils.isNotEmpty(addResultStr)) {
                        Sqfw_datamange_district sqfwDatamangeDistrict1 = dataMangeDistrictService.fetch(Cnd.where(Sqfw_datamange_district::getSqfwSummaryId, "=", summaryId));
                        String excelData = sqfwDatamangeDistrict1.getExcelData().substring(0, sqfwDatamangeDistrictSummary.getExcelData().length() - 1);
                        excelData = excelData + addResultStr.toString() + "]";
                        sqfwDatamangeDistrict1.setExcelData(JSONUtil.toJsonStr(excelData));
                        log.info("report add sql-- {}", JSONUtil.toJsonStr(sqfwDatamangeDistrict1));
                        sqfwDatamangeDistrict1.setParamData(CommunityDataCleanUtils.parseExcelDataForParamdata(excelData));
                        dataMangeDistrictService.updateIgnoreNull(sqfwDatamangeDistrict1);
                    }
                }
            }
        } catch (Exception ex) {
            log.error("街道to区县主表解析json异常, {}" + ex.getMessage());
        }

    }

    private void updateMainTableProcess() {

    }

    private SqfwDataMangeCheckVO communityDataCheckByType(List<String> ids, String type) {
        if (ObjectUtils.isEmpty(ids) || StringUtils.isEmpty(type)) {
            throw new AppException(ResultCode.PARAM_ERROR.getMsg());
        }
        List<Sqfw_formSummary_new> sqfwFormSummaryNewList = sqfwFormsummaryNewService.query(Cnd.where("id", "IN", ids));
        // 获取所有相关数据字段
        String configJson = CommunityDataCleanUtils.queryDictFieldInfoByType(type);
        if (StringUtils.isEmpty(configJson)) {
            log.info("===============未查询到对应的数据字典field type===============");
            return new SqfwDataMangeCheckVO();
        }
        LinkedHashMap<String, String> fieldMap = new LinkedHashMap<>();
        CommunityDataCleanUtils.parseDictFeild(configJson, fieldMap);

        List<SqfwFormSummaryOnlineDTO> onlineList = Collections.synchronizedList(new ArrayList<SqfwFormSummaryOnlineDTO>());

        SqfwFormSummaryOnlineDTO sqfwFormSummaryOnlineDTO = new SqfwFormSummaryOnlineDTO();
        sqfwFormSummaryOnlineDTO.setExcelDataMap(fieldMap);
        onlineList.add(sqfwFormSummaryOnlineDTO);

        // 清洗param_data数据
        CommunityDataCleanUtils.cleanParamData(sqfwFormSummaryNewList, onlineList, fieldMap);

        // 组装excel数据,需要排序，所以插入表操作分开写
        Sqfw_datamange_community sqfwDatamangeHeader = new Sqfw_datamange_community();
        List<Sqfw_datamange_community> sqfwFormSummaryOnlines = Collections.synchronizedList(new ArrayList<Sqfw_datamange_community>());
        buildExcelData(onlineList, sqfwDatamangeHeader, sqfwFormSummaryOnlines, type);

        // 插入表
        Sys_user sysUser = sysUserService.fetch(SecurityUtil.getUserId());
        Sqfw_datamange_street_check sqfwDatamangeStreetCheck = new Sqfw_datamange_street_check();
        sqfwDatamangeStreetCheck
                .setId(R.UU32())
                .setProvince(sysUser.getProvince())
                .setCity(sysUser.getCity())
                .setDistrict(sysUser.getDistrict())
                .setCounty(sysUser.getCounty())
                .setCommunity(sysUser.getCommunity())
                .setCreateBy(sysUser.getId())
                .setCreateUserName(sysUser.getUsername())
                .setDelFlag(false)
                .setUnitId(sysUser.getUnitId())
                .setUnitName(sysUser.getUnitName())
                .setType(type);
        StringBuffer sb = new StringBuffer();
        sb.append(sqfwDatamangeHeader.getExcelData()).append(",");
        sqfwFormSummaryOnlines.forEach(sqfwDatamangeCommunity -> {
            sb.append(sqfwDatamangeCommunity.getExcelData()).append(",");
        });
        String excelDataAll = "[" + sb.substring(0, sb.lastIndexOf(",")) + "]";
        sqfwDatamangeStreetCheck.setExcelData(JSONUtil.toJsonStr(excelDataAll));
        SqfwDataMangeCheckVO sqfwDataMangeCheckVO = new SqfwDataMangeCheckVO();
        BeanUtil.copyProperties(sqfwDatamangeStreetCheck, sqfwDataMangeCheckVO);
        return sqfwDataMangeCheckVO;
    }

    /**
     * 组件excel数据,并插入数据库
     */
    private void buildExcelData(List<SqfwFormSummaryOnlineDTO> onlineList, Sqfw_datamange_community sqfwDatamangeHeader, List<Sqfw_datamange_community> sqfwFormSummaryOnlines, String type) {
        String commonId = R.UU32();
        ThreadPoolExecutor threadPoolExecutor = ThreadPoolExecutorUtil.getInstance();
        CompletableFuture[] cf = onlineList.stream().map(item -> CompletableFuture.runAsync(() ->
                        processExcelData(item, sqfwDatamangeHeader, sqfwFormSummaryOnlines, commonId, type), threadPoolExecutor)
                .thenApplyAsync(r -> r)).toArray(CompletableFuture[]::new);
        CompletableFuture.allOf(cf).join();
        log.info("===========================组装Excel报文完成：{}条===========================", sqfwFormSummaryOnlines.size());
       /* onlineList.forEach(item->{
            processExcelData(item, rowCount, numCount, commonId, sqfwOnlineService);
        });*/
    }

    /**
     * 处理excel数据
     */
    private void processExcelData(SqfwFormSummaryOnlineDTO sqfwFormSummaryOnlineDTO, Sqfw_datamange_community sqfwDatamangeHeader,
                                  List<Sqfw_datamange_community> sqfwFormSummaryOnlines, String commonId, String type) {
        //synchronized (LOCK) {
        List<SqfwExcelOnlineAllDTO> sqfwExcelOnlineAllDTOS = Collections.synchronizedList(new ArrayList<SqfwExcelOnlineAllDTO>());
        String updateDate = CommunityDataCleanUtils.formatDate(String.valueOf(sqfwFormSummaryOnlineDTO.getCreateDate()));
        AtomicInteger colCount = new AtomicInteger(0);
        for (ConcurrentSkipListMap.Entry<String, String> entry : sqfwFormSummaryOnlineDTO.getExcelDataMap().entrySet()) {
            // 解析到excelJson
            SqfwExcelOnlineAllDTO sqfwExcelOnlineAllDTO = new SqfwExcelOnlineAllDTO();
            sqfwExcelOnlineAllDTO = CommunityDataCleanUtils.parseSummaryData(entry, updateDate);
            sqfwExcelOnlineAllDTOS.add(sqfwExcelOnlineAllDTO);
            sqfwFormSummaryOnlineDTO.setExcelData(JSONUtil.toJsonStr(sqfwExcelOnlineAllDTOS));
            colCount.getAndIncrement();
        }
        sqfwFormSummaryOnlineDTO.setColNum(String.valueOf(colCount.get()));
        log.info("============id:{}, 总列数：{}============", sqfwFormSummaryOnlineDTO.getSqfwSummaryId(), colCount.getAndIncrement());
        sqfwFormSummaryOnlineDTO.setCommonId(commonId);
        sqfwFormSummaryOnlineDTO.setId(R.UU32());
        sqfwFormSummaryOnlineDTO.setDelFlag(false);
        sqfwFormSummaryOnlineDTO.setSqfwSummaryId(sqfwFormSummaryOnlineDTO.getSqfwSummaryId());
        if (StringUtils.isEmpty(sqfwFormSummaryOnlineDTO.getSqfwSummaryId())) {
            sqfwFormSummaryOnlineDTO.setExcelSeg("header");
            BeanUtil.copyProperties(sqfwFormSummaryOnlineDTO, sqfwDatamangeHeader);
        } else {
            sqfwFormSummaryOnlineDTO.setType(type);
            sqfwFormSummaryOnlineDTO.setExcelSeg("body");
            sqfwFormSummaryOnlines.add(sqfwFormSummaryOnlineDTO);
        }
        //}
    }

    /**
     * 将清洗好的Excel数据插入数据库
     */
    @Aop(TransAop.READ_COMMITTED)
    @CacheRemove
    private void excelDataBatchInsert(List<Sqfw_datamange_community> onlineList) {
        ThreadPoolExecutor threadPoolExecutor = ThreadPoolExecutorUtil.getInstance();
        CompletableFuture[] cf = onlineList.stream().map(item -> CompletableFuture.runAsync(() ->
                        this.insert(item), threadPoolExecutor)
                .thenApplyAsync(r -> r)).toArray(CompletableFuture[]::new);
        CompletableFuture.allOf(cf).join();
    }

    /**
     * 构造查询条件
     *
     * @param bean
     * @return
     */
    private Criteria buildQueryCond(SqfwDataMangeCheckVO bean) {
        Criteria cri = Cnd.cri();
        SqlExpressionGroup criSql = cri.where();
        // 不查询excel头
        criSql.andNotEquals(Sqfw_datamange_community::getExcelSeg, "header");
        criSql.andEquals(Sqfw_datamange_community::getDelFlag, false);
        if (null != bean && StringUtils.isNotEmpty(bean.getPlaceType())) {
            criSql.andLike("param_data->>'placeType'", bean.getPlaceType());
        }
        if (null != bean && StringUtils.isNotEmpty(bean.getCommunity())) {
            criSql.andLike(Sqfw_datamange_community::getCommunity, bean.getCommunity());
        }
        return cri;
    }
}
